11593. Преобразовать
в перестановку
Имеется массив A размера n.
За одну операцию можно выбрать индекс i (1 ≤ i ≤ n)
и увеличить Ai на 1.
Найдите минимальное количество
операций, необходимое для преобразования массива A в перестановку размера n.
Если это невозможно, выведите -1.
Обратите внимание, что
перестановка размера n содержит каждый элемент от 1 до n ровно
один раз.
Вход. Первая строка содержит количество
тестов T.
Каждый тест состоит из нескольких
строк. Первая строка каждого теста содержит одно целое число n (1 ≤ n ≤ 1000)
– размер массива. В следующей строке записаны n целых чисел – элементы
массива A (0 ≤ Ai ≤ 1000).
Выход. Для каждого теста выведите в
новой строке минимальное количество операций, необходимое для преобразования
массива A в перестановку размера n.
Если это сделать невозможно, то
выведите -1.
Пример
входа |
Пример
выхода |
4 4 3 1 1 2 3 0 3 3 3 3 2 1 3 2 0 1 |
3 -1 0 3 |
жадность
Отсортируем входной массив: a0, a1,
…, an – 1. Для того чтобы получить перестановку (1, 2, …, n), необходимо произвести
следующие преобразования:
a0 → 1, a1 → 2, …, an – 1 → n
То есть из числа
ai следует сделать
i + 1. Нам доступна только одна операция по преобразованию чисел:
увеличение на 1. Если изначально ai > i + 1, то из ai получить i
+ 1 невозможно. Иначе i + 1 из ai можно получить
за i + 1 – ai операций. Осталось просуммировать это
количество операций для каждого i от 0 до n – 1.
Пример
Отсортируем
массив в первом тесте: (1, 1, 2, 3). Нам следует получить перестановку (1, 2, 3, 4). Количество
операций равно
(1 – 1) + (2 –
1) + (3 – 2) + (4 – 3) = 0 + 1 + 1 + 1= 3
Во втором тесте
после сортировки массив примет вид: (0, 3, 3). Получить перестановку (1, 2, 3) невозможно, так как нельзя a1 = 3
преобразовать в 2.
Реализация алгоритма
Читаем количество тестов tests.
scanf("%d", &tests);
while (tests--)
{
Читаем входные данные текущего теста.
scanf("%d", &n);
v.clear(); v.resize(n);
for (i = 0; i < n; i++)
scanf("%d", &v[i]);
Сортируем массив.
sort(v.begin(), v.end());
В переменной res подсчитываем минимальное количество операций по
преобразованию входной последовательности в перестановку размера n.
res = 0;
Перебираем индексы i от 0 до n – 1.
for (i = 0; i < n; i++)
{
Если vi > i + 1, то из vi получить i
+ 1 невозможно. Преобразовать входной массив в перестановку нельзя.
if (v[i] > i + 1)
{
res = -1;
break;
}
Суммируем требуемое количество операций.
res += (i + 1 - v[i]);
}
Выводим ответ.
printf("%d\n", res);
}